package com.itnature.testchip.process;

import java.text.DecimalFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.NavigableMap;
import java.util.Properties;
import java.util.TreeMap;
import java.util.Vector;

import org.apache.log4j.Logger;

import com.itnature.testchip.business.HeaderFooter;
import com.itnature.testchip.business.StopBin;
import com.itnature.testchip.business.TestSuite;
import com.itnature.testchip.business.Timing;
import com.itnature.testchip.business.VDDDetail;
import com.itnature.testchip.business.VDDSummary;

public class TestChipProcessing {

	private static final String CHECK = "CHECK";
	private static final String DATE_FORMAT = "MM/dd/yyyy";
	public static Vector<String> VecAllVddKey = new Vector<String>();
	private static SimpleDateFormat formater;
	/*
	 * public static String searchKeys_forVDDDetail[] = { "iol_33", "ioh_33", "iol_25", "ioh_25", "iovdd_lev", "corevdd_lev", "vdd25_lev",
	 * "pll123vdd_lev", "avdd_lev", "rtcvdd_lev", "usb20vdd_lev", "vil_lev", "vih_lev", "vol_lev", "voh_lev", "vcl_lev", "vch_lev",
	 * "vil25_lev", "vih25_lev", "vol25_lev", "voh25_lev", "vcl25_lev", "vch25_lev", "iol_2ma", "ioh_2ma", "iol_4ma", "ioh_4ma", "iol_8ma",
	 * "ioh_8ma", "trigger_high", "trigger_low" };
	 */

	private static final String VECTOR_LABEL = "override_seqlbl";
	private static final String TEST_FUNC = "override_testf";
	private static final String ANASET = "override_anaset";
	private static final String LEVEL_SET = "override_levset";
	private static final String LEVEL_SPEC = "override_lev_spec_set";
	private static final String LEVEL_EQUATION = "override_lev_equ_set";
	private static final String TIMING_SET = "override_timset";
	private static final String TIMING_SPEC = "override_tim_spec_set";
	private static final String TIMING_EQUATION = "override_tim_equ_set";

	public static Vector<StopBin> getStopBins(String tfContent) {
		Vector<String> stopBinString = getStopBinString(tfContent);
		Vector<StopBin> stopBins = getStopBins(stopBinString);
		return stopBins;
	}

	// =========================================================
	// get header footer
	public static HeaderFooter getHeaderFooter(String tfContent, String fileName) {
		HeaderFooter rs = new HeaderFooter();

		String headerContent = getContentWithKey(tfContent, "information", "end");
		parseHeader(headerContent, rs, fileName);
		if (rs.getProgramName() != null) {
			rs.setProgramName(rs.getProgramName().toUpperCase());
		}

		String footerContent = getContentWithKey(tfContent, "context", "end");
		parseFooter(footerContent, rs);
		return rs;
	}

	private static void parseFooter(String footerContent, HeaderFooter rs) {
		footerContent = footerContent.replace("\n", "");
		footerContent = footerContent.replace("\"", "");

		Properties p = new Properties();

		String[] arr = footerContent.split(";");
		for (String val : arr) {
		    val = val.trim();
//		    System.out.println(val);
            if (!val.isEmpty()) {
                String[] arrPro = val.split("=");
                String prop = arrPro.length > 1 ? arrPro[1].trim() : "";
                p.put(arrPro[0].trim(), prop);
            }
		}

		rs.setConfigFile(p.getProperty("context_config_file"));
		rs.setLevelFile(p.getProperty("context_levels_file"));
		rs.setTimingFile(p.getProperty("context_timing_file"));
		rs.setVectorFile(p.getProperty("context_vector_file"));
		rs.setAttributeFile(p.getProperty("context_attrib_file"));
		rs.setAnalogFile(p.getProperty("context_analog_control_file"));
		rs.setWaveFormFile(p.getProperty("context_waveform_file"));
		rs.setRoutingFile(p.getProperty("context_routing_file"));

		/*
		 * String []arrPro = arr[0].split("="); rs.setConfigFile(arrPro[1].trim());
		 * 
		 * arrPro = arr[1].split("="); rs.setLevelFile(arrPro[1].trim());
		 * 
		 * arrPro = arr[2].split("="); rs.setTimingFile(arrPro[1].trim());
		 * 
		 * arrPro = arr[3].split("="); rs.setVectorFile(arrPro[1].trim());
		 * 
		 * arrPro = arr[4].split("="); rs.setAttributeFile(arrPro[1].trim());
		 * 
		 * arrPro = arr[5].split("="); rs.setAnalogFile(arrPro[1].trim());
		 * 
		 * arrPro = arr[6].split("="); rs.setWaveFormFile(arrPro[1].trim());
		 * 
		 * arrPro = arr[7].split("="); rs.setRoutingFile(arrPro[1].trim());
		 */
	}

	/**
	 * @param headerContent
	 * @param rs
	 * @param fileName
	 * @param testProgramName
	 */
	private static void parseHeader(String headerContent, HeaderFooter rs, String fileName) {
		headerContent = headerContent.replace("\n", "");
		headerContent = headerContent.replace("\"", "");

		String[] arr = headerContent.split(";");
		String device = "", rev = "", testRev = "";

		for (String line : arr) {
			String[] arrPro = line.split("=");
			String arrPro0 = arrPro[0].trim();
			if (arrPro0.equals("device_name")) {
				device = arrPro[1].trim();
			} else if (arrPro0.equals("device_revision")) {
				rev = arrPro[1].trim();
			} else if (arrPro0.equals("test_revision")) {
				testRev = arrPro[1].trim();
			}
		}

		rs.setDevice(device + " rev " + rev);
		String programName = null;
		if (fileName == null) {
			programName = device + "_ft_rev" + rev + "_r" + testRev;
		} else {
			if (fileName.endsWith("_TP") || fileName.endsWith("_tp")) {
				programName = fileName;
			} else if (fileName.endsWith("_TF")) {
				programName = fileName.replaceAll("_TF", "_TP");
			} else if (fileName.endsWith("_tf")) {
				programName = fileName.replaceAll("_tf", "_tp");
			} else {
				programName = fileName + "_TP";
			}
		}
		// String programName = device + "_ft_rev" + rev + "_r" + testRev +
		// "_tp";
		rs.setProgramName(programName.toLowerCase());
		String revNumber = null;
		try {
			Double.parseDouble(testRev);
			revNumber = testRev;
		} catch (Exception e) {
			revNumber = "0.0";
		}
		rs.setRevision(revNumber);
	}

	private static String getContentWithKey(String tfContent, String startKey, String stopKey) {
		int idx = tfContent.indexOf(startKey) + startKey.length();
		String headerContent = tfContent.substring(idx);
		idx = headerContent.indexOf(stopKey);
		headerContent = headerContent.substring(0, idx);
		return headerContent;
	}

	// =========================================================
	// search stop_bin
	private static Vector<StopBin> getStopBins(Vector<String> stopBinString) {
		String startKey = "stop_bin";
		Vector<StopBin> vec = new Vector<StopBin>();
		for (String stopBin : stopBinString) {
			StopBin bin = new StopBin();

			String[] tmp = stopBin.split("###");
			bin.setTestName(tmp[1]);

			if (vec.size() == 34) {
				int i = 0;
			}
			// Note: ThienTran edit at Apr 18, 2009
			// get stopbin
			stopBin = stopBin.replace(startKey, "");
			String[] arr = stopBin.split(",");
			if (arr.length > 8) {
				stopBin = stopBin.substring(0, stopBin.lastIndexOf("\""));
				stopBin = stopBin.substring(stopBin.lastIndexOf("\"") + 1);
				bin.setBinName(stopBin);
			} else {
				bin.setBinName(arr[1].trim().replace("\"", ""));
			}
			bin.setSoftBin(arr[0].trim().replace("\"", ""));
			bin.setHardBin(arr[arr.length - 2].trim().replace("\"", ""));
			bin.setBinName(bin.getBinName().replace(" ", "_"));

			if (bin.getBinName().equals("PASS")) {
				bin.setTestName("PASS");
			}

			vec.add(bin);

			// System.out.println(bin.getSoftBin() + " idx: "+vec.size());
		}
		return vec;
	}

	private static Vector<String> getStopBinString(String tfContent) {
		Vector<String> rs = new Vector<String>();
		String startKey = "stop_bin";
		String stopKey = ";";

		while (tfContent.indexOf(startKey) >= 0) {
			// Note: ThienTran edit at Apr 18, 2009
			// get run_and_branch string
			int idx = tfContent.indexOf(startKey); // idx of stop_bin
			String tmp = tfContent.substring(0, idx);
			int idxStartRunBranch = tmp.lastIndexOf("run_and_branch");
			if (idxStartRunBranch == -1 || idxStartRunBranch >= idx) {
				tmp = "PASS";
			} else {
				int idxStopRunBranch = tmp.lastIndexOf(")");
				tmp = tfContent.substring(idxStartRunBranch, idxStopRunBranch);
				tmp = tmp.substring(tmp.indexOf("(") + 1);
			}

			// Note: ThienTran edit at Apr 18, 2009
			// get stop_bin string
			tfContent = tfContent.substring(idx);
			String stopBin = tfContent.substring(0, tfContent.indexOf(stopKey));
			rs.add(stopBin + "###" + tmp);
			tfContent = tfContent.substring(tfContent.indexOf(stopKey) + 1);
		}

		return rs;
	}

	// =========================================================
	// get test suite detail
	public static Vector<TestSuite> getTestSuites(String fileContent, Vector<StopBin> stopBins) {
		Vector<TestSuite> vec = new Vector<TestSuite>();
		// search and get testsuite
		for (int i = 0; i < stopBins.size(); i++) {
			if (i == 20) {
				System.out.print("");
			}
			StopBin stopBin = stopBins.get(i);
			String searchKey = stopBin.getTestName();
			// String searchKey = stopBin.getBinName();

			String tsFragment = getTestSuiteFragment(fileContent, searchKey);

			TestSuite testSuite = parseTestSuite(tsFragment);
			if (tsFragment != null) {
				// search test function full name
				String function = fileContent.substring(fileContent.indexOf(testSuite.getTestFunction() + ":"));
				function = function.substring(function.indexOf("\"") + 1, function.indexOf(";") - 1);
				testSuite.setTestFunction(function);
			}

			vec.add(testSuite);
		}
		return vec;
	}

	private static TestSuite parseTestSuite(String tsFragment) {
		TestSuite ts = new TestSuite();
		HashMap<String, String> hash = getInitTestSuite();

		if (tsFragment != null) {
			tsFragment = tsFragment.replace("\n", "");
			String[] tsAttr = tsFragment.split(";");
			for (String attr : tsAttr) {
				String[] arr = attr.split("=");
				if (attr.contains(TIMING_EQUATION)) {
					// hash.put(TIMING_EQUATION,arr[1].trim());
					ts.setTimingEquation(arr[1].trim());

				} else if (attr.contains(TIMING_SPEC)) {
					// hash.put(TIMING_SPEC,arr[1].trim());
					ts.setTimingSpec(arr[1].trim());

				} else if (attr.contains(TIMING_SET)) {
					// hash.put(TIMING_SET,arr[1].trim());
					ts.setTimingSet(arr[1].trim());

				} else if (attr.contains(LEVEL_EQUATION)) {
					// hash.put(LEVEL_EQUATION,arr[1].trim());
					ts.setLevelEquation(arr[1].trim());

				} else if (attr.contains(LEVEL_SPEC)) {
					// hash.put(LEVEL_SPEC,arr[1].trim());
					ts.setLevelSpec(arr[1].trim());

				} else if (attr.contains(LEVEL_SET)) {
					// hash.put(LEVEL_SET,arr[1].trim());
					ts.setLevelSet(arr[1].trim());

				} else if (attr.contains(VECTOR_LABEL)) {
					// hash.put(VECTOR_LABEL,arr[1].trim());
					ts.setVectorLabel(arr[1].trim().replace("\"", ""));

				} else if (attr.contains(ANASET)) {
					// hash.put(ANASET,arr[1].trim());
					ts.setAnalogSet(arr[1].trim());

				} else if (attr.contains(TEST_FUNC)) {
					// hash.put(TEST_FUNC,arr[1].trim());
					ts.setTestFunction(arr[1].trim());

				}
			}
		}

		// ts.setTimingEquation(hash.get(TIMING_EQUATION));
		// ts.setTimingSpec(hash.get(TIMING_SPEC));
		// ts.setTimingSet(hash.get(TIMING_SET));
		//		
		// ts.setLevelEquation(hash.get(LEVEL_EQUATION));
		// ts.setLevelSpec(hash.get(LEVEL_SPEC));
		// ts.setLevelSet(hash.get(LEVEL_SET));
		//		
		// ts.setVectorLabel(hash.get(VECTOR_LABEL).replace("\"", ""));
		// ts.setAnalogSet(hash.get(ANASET));
		// ts.setTestFunction(hash.get(TEST_FUNC));
		return ts;
	}

	// return test suite fragment
	private static String getTestSuiteFragment(String fileContent, String searchKey) {
		int idxStart = fileContent.indexOf(searchKey + ":");
		String rs = "";
		if (idxStart == -1) {
			String fContentLower = fileContent.toLowerCase();
			idxStart = fContentLower.indexOf((searchKey + ":").toLowerCase());
			if (idxStart == -1) {
				int step = 1;
				int idx = fContentLower.indexOf(searchKey + step + ":");
				while (idx >= 0) {
					step++;
					idx = fContentLower.indexOf(searchKey + step + ":");
				}
				step -= 1;
				idxStart = fContentLower.indexOf(searchKey + step + ":");
				if (idxStart == -1) {
					return null;
				}
			}
		}

		String testSuite = fileContent.substring(idxStart + (searchKey + ":").length());
		int idxTestFunction = testSuite.indexOf(TEST_FUNC);
		String temp = testSuite.substring(idxTestFunction);
		int idxSemicolon = temp.indexOf(";") + 1;
		testSuite = testSuite.substring(0, idxTestFunction + idxSemicolon);
		rs = testSuite.substring(testSuite.indexOf(";") + 1, testSuite.lastIndexOf(";"));
		return rs;
	}

	private static HashMap<String, String> getInitTestSuite() {
		HashMap<String, String> hash = new HashMap<String, String>();
		hash.put(TIMING_EQUATION, "");
		hash.put(TIMING_SPEC, "");
		hash.put(TIMING_SET, "");
		hash.put(LEVEL_EQUATION, "");
		hash.put(LEVEL_SPEC, "");
		hash.put(LEVEL_SET, "");
		hash.put(ANASET, "");
		hash.put(TEST_FUNC, "");
		hash.put(VECTOR_LABEL, "");
		return hash;
	}

	public static Vector<Timing> getTimings(String timingContent, Vector<TestSuite> testSuites) {
		timingContent = timingContent.toLowerCase();
		Vector<Timing> vecTiming = new Vector<Timing>();
		int i = 0;
		for (TestSuite testSuite : testSuites) {
			if (i == 3) {
				int j = 0;
			}

			Timing timing = new Timing();

			if (testSuite.getTimingEquation().equals("") || testSuite.getTimingSpec().equals("")) {
				timing.setFreq("");
				timing.setTimming("");
				timing.setVdd("");
				vecTiming.add(timing);
				i++;
				continue;
			}

			String searchKey = "eqnset " + testSuite.getTimingEquation() + " \"";
			int idx = indexOfWithPos(timingContent, searchKey, 2);
			if (idx == -1) {
				idx = indexOfWithPos(timingContent, searchKey, 1);
			}


			if (idx == -1) {
				Logger.getLogger(TestChipProcessing.class).error(searchKey + " not found in Timing file");
			} else {
//			    System.out.println("\n\n============:\n"+testSuite.getTimingEquation());
			    String tim = timingContent.substring(idx);
			    tim = tim.substring(tim.indexOf("\"") + 1);
			    tim = tim.substring(0, tim.indexOf("\"")).trim();
			    timing.setTimming(tim);
			    
				String tmp = timingContent.substring(idx);

				searchKey = "specset " + testSuite.getTimingSpec() + " \"";

				try {
					idx = tmp.indexOf(searchKey);
					if (idx == -1) {
						Logger.getLogger(TestChipProcessing.class).error(searchKey + " not found in Timing file");
					} else {
						String temp = tmp.substring(idx);
						temp = getFreq(temp);
						timing.setFreq(temp);
					}
				} catch (Exception e) {
					int j = 0;
					timing.setFreq("");
				}
			}

			vecTiming.add(timing);
			i++;
		}
		return vecTiming;
	}

	private static String getFreq(String temp) {
		String rs = null;
		String nextTmp = temp;
		String search = "# specname";

		nextTmp = nextTmp.substring(nextTmp.indexOf(search));
		nextTmp = nextTmp.substring(nextTmp.indexOf("\n") + 1);

		while (rs == null) {
			String tmp = nextTmp.substring(0, nextTmp.indexOf("]"));

			if (tmp.contains("frequency") || tmp.contains("Frequency")) {
				tmp = tmp.substring(tmp.indexOf(" "));
				tmp = tmp.trim() + " ";
				rs = tmp.substring(0, tmp.indexOf(" "));
			} else if (tmp.contains("tc") || tmp.contains("per_")) {
				tmp = tmp.substring(tmp.indexOf(" "));
				tmp = tmp.trim() + " ";
				tmp = tmp.substring(0, tmp.indexOf(" "));
				double t = Double.parseDouble(tmp);
				if (t != 0) {
					double freq = (1 / t) * 1000;
					DecimalFormat f = new DecimalFormat("0.00");
					rs = f.format(freq);
				}
			}

			nextTmp = nextTmp.substring(nextTmp.indexOf("\n") + 1);
		}
		return rs;
	}

	public static Vector<Timing> getVdd(String lvlContent, Vector<TestSuite> testSuites, Vector<Timing> timings) {
		// String lvlContentLower = lvlContent.toLowerCase();
		int i = 0;
		for (TestSuite testSuite : testSuites) {
			if (i == 20) {
				System.out.println();
			}

			if (testSuite.getLevelEquation().equals("") || testSuite.getLevelSpec().equals("")) {
				timings.get(i).setVdd("");
				i++;
				continue;
			}

			String eqnsetSearchKey = ("EQNSET " + testSuite.getLevelEquation() + " ");
			// int idx = lvlContent.indexOf(searchKey);
			int idx = indexOfWithPos(lvlContent, eqnsetSearchKey, 2);

			if (idx == -1) {
				Logger.getLogger(TestChipProcessing.class.getName()).error(eqnsetSearchKey + " not found in Level file");

				timings.get(i).setVdd("");

			} else {
				String temp = lvlContent.substring(idx);

				String specsetSearchKey = "SPECSET " + testSuite.getLevelSpec() + " ";
				idx = temp.indexOf(specsetSearchKey);
				if (idx > -0) {
					temp = temp.substring(idx);

					temp = temp.substring(temp.indexOf("\"") + 1);
					temp = temp.substring(0, temp.indexOf("\""));

					timings.get(i).setVdd(temp);
				} else {
					timings.get(i).setVdd(CHECK);
					Logger.getLogger(TestChipProcessing.class.getName()).error(eqnsetSearchKey + "," + specsetSearchKey + " not found in Level file");
				}

			}
			i++;
		}
		return timings;
	}

	// Note: ThienTran edit at Dec 20, 2008
	// error
	public static Vector<VDDSummary> getVddSummary(Vector<TestSuite> testSuites, Vector<Timing> timings) {
		// HashMap<String, String> equaSpec = new HashMap<String, String>();
		/*
		 * TreeMap<String, String> equaSpec = new TreeMap<String, String>(new Comparator<String>() {
		 * 
		 * public int compare(String arg0, String arg1) { try { Integer n0 = new Integer(arg0); Integer n1 = new Integer(arg1); return
		 * n0.compareTo(n1); } catch (Exception e) { Logger.getLogger(TestChipProcessing.class.getName()).debug(e); } return
		 * arg0.compareTo(arg1); }
		 * 
		 * });
		 */
		TreeMap<String, String> equaSpec = new TreeMap<String, String>();
		for (int i = 0; i < testSuites.size(); i++) {
			if (testSuites.get(i).getTimingEquation().equals("") || testSuites.get(i).getTimingSpec().equals("")) {
				continue;
			}

			String key = testSuites.get(i).getLevelEquation() + "," + testSuites.get(i).getLevelSpec();
			String vdd = (i < timings.size()) ? timings.get(i).getVdd().replace("vdd ", "") : "";
			equaSpec.put(key, vdd);
		}
		NavigableMap<String, String> map = equaSpec.descendingMap();
		Vector<VDDSummary> vec = new Vector<VDDSummary>();
		for (String key : map.keySet()) {
			VDDSummary vdd = new VDDSummary();
			String[] arr = key.split(",");
			vdd.setEquation(arr[0]);
			vdd.setSpec(arr[1]);
			vdd.setVdd(map.get(key));
			vec.add(vdd);
		}
		Vector<VDDSummary> rs = new Vector<VDDSummary>();
		for (int i = vec.size() - 1; i >= 0; i--) {
			rs.add(vec.get(i));
		}
		return rs;
	}

	public static Vector<VDDDetail> getVddDetail(String lvlContent, Vector<VDDSummary> vddSummaries) {
		VecAllVddKey.clear();
		Vector<VDDDetail> vddDetails = new Vector<VDDDetail>();
		for (int i = 0; i < vddSummaries.size(); i++) {
			VDDSummary vddSummary = vddSummaries.get(i);

			String vddFragment = getVddFragment(lvlContent, vddSummary.getEquation(), vddSummary.getSpec());
			VDDDetail details = parseToVDDDetails(vddFragment);
			vddDetails.add(details);
		}
		return vddDetails;
	}

	private static VDDDetail parseToVDDDetails(String vddFragment) {
		VDDDetail detail = new VDDDetail();
		int idx;
		int offset = 0;
		// Note: ThienTran edit at May 5, 2009
		// iovdd_lev or iovdd_level ==> offset is length of "el" in "_level"
		if (vddFragment.indexOf("_level") != -1) {
			offset = 2;
		}

		String arr[] = vddFragment.split("\n");
		for (String info : arr) {
			if (info.contains("#") || !info.contains("[") || !info.contains("]")) {
				continue;
			}
			info = info.trim();
			if (info.length() != 0) {
				String key = info.substring(0, info.indexOf(' '));
				info = info.substring(info.indexOf(' ')).trim();
				String value = info.substring(0, info.indexOf(' '));
				detail.putDetail(key, value);

				if (!VecAllVddKey.contains(key)) {
					VecAllVddKey.add(key);
				}
			}
		}

		/*
		 * for(int i=0 ; i<searchKeys_forVDDDetail.length ; i++) { String searchKey = searchKeys_forVDDDetail[i]; idx =
		 * vddFragment.indexOf(searchKey); if(idx!=-1) { String temp = vddFragment.substring(idx); int idxEnd = temp.indexOf("["); String
		 * tmp = vddFragment.substring(idx + searchKey.length() + offset,idxEnd + idx).trim(); detail.putDetail(searchKey, tmp); } }
		 */

		return detail;
	}

	private static String getVddFragment(String lvlContent, String equation, String spec) {
		String eqnsetSearchKey = "EQNSET " + equation + " ";
		int idx = lvlContent.lastIndexOf(eqnsetSearchKey);
		// if idx == -1 ( equation = 5)
		if (idx == -1) {
			Logger.getLogger(TestChipProcessing.class.getName()).error(eqnsetSearchKey + " not found in Level file");

			eqnsetSearchKey = ("EQNSET " + ((new Integer(equation)).intValue() - 1) + " ");
			idx = lvlContent.lastIndexOf(eqnsetSearchKey);
			String temp = lvlContent.substring(idx);

			eqnsetSearchKey = ("EQNSET 1 ");
			idx = temp.lastIndexOf(eqnsetSearchKey);
			temp = temp.substring(idx);

			String specsetSearchKey = "SPECSET " + spec + " ";
			idx = temp.indexOf(specsetSearchKey);
			temp = temp.substring(idx);

			idx = temp.indexOf("iovdd_level");
			temp = temp.substring(idx);

			int idxEnd = temp.indexOf("dmar0_vih_level");
			String tempo = temp.substring(idxEnd);
			idxEnd += tempo.indexOf("]") + 1;

			temp = temp.substring(0, idxEnd);
			return temp;

		}
		lvlContent = lvlContent.substring(idx);

		String specsetSearchKey = "SPECSET " + spec + " ";
		idx = lvlContent.indexOf(specsetSearchKey);
		if (idx == -1) {
			Logger.getLogger(TestChipProcessing.class.getName()).error(eqnsetSearchKey + "," + specsetSearchKey + " not found in Level file");
			return "";
		}
		lvlContent = lvlContent.substring(idx);
		lvlContent = lvlContent.substring(lvlContent.indexOf("# SPECNAME"));
		lvlContent = lvlContent.substring(lvlContent.indexOf("\n"));
		lvlContent = lvlContent.trim();

		int idxStop = -1;
		int idxStart1 = lvlContent.indexOf("SPECSET");
		int idxStart2 = lvlContent.indexOf("EQNSET");
		if (idxStart1 == -1 && idxStart2 == -1) {
			idxStop = lvlContent.indexOf("@");
		} else {
			if (idxStart1 < idxStart2 || idxStart2 == -1) {
				idxStop = idxStart1;
			} else {
				idxStop = idxStart2;
			}
		}
		lvlContent = lvlContent.substring(0, idxStop).trim();

		return lvlContent;
	}

	private static int indexOfWithPos(String lvlContent, String searchKey, int time) {
		if (time <= 0)
			return -1;
		int rs = 0;
		for (int i = 0; i < time; i++) {
			int idx = lvlContent.indexOf(searchKey);
			// System.out.println(lvlContent);
			if (idx == -1) {
				return -1;
			} else {
				rs += idx;
			}
			lvlContent = lvlContent.substring(idx + searchKey.length());
		}
		return rs;
	}

	public static SimpleDateFormat getFormater() {
		if (formater == null) {
			formater = new SimpleDateFormat(DATE_FORMAT);
		}
		return formater;
	}

	public static String format(Date d) {
		return getFormater().format(d);
	}

	public static Date parse(String dateString) {
		try {
			return getFormater().parse(dateString);
		} catch (ParseException e) {
			return null;
		}
	}
}
